#ifndef THREADPOOL_H
#define THREADPOOL_H

#include <mutex>
#include <condition_variable>
#include <queue>
#include <thread>
#include <functional>

//线程池
class ThreadPool {
public:
    explicit ThreadPool(size_t threadCount = 8): pool_(std::make_shared<Pool>()) { //explicit关键字的作用是表明该构造函数是显示的,防止类构造函数的隐式自动转换 make_shared 创建空对象
            assert(threadCount > 0); //检查传入参数是否合法，assert断言，如果为假终止程序
            for(size_t i = 0; i < threadCount; i++) { //循环创建指定个数的子线程
                std::thread([pool = pool_] { //大括号内为线程需要执行的代码，这里是lambda表达式
                    std::unique_lock<std::mutex> locker(pool->mtx); //unique_lock独占指针，传递未被使用的mutex，通过。会上锁，无法获得锁时会阻塞
                    while(true) {
                        if(!pool->tasks.empty()) { //线程池中有任务
                            //从任务队列中取任务
                            auto task = std::move(pool->tasks.front());
                            //移除任务
                            pool->tasks.pop();
                            locker.unlock(); //解锁
                            task(); //任务处理
                            locker.lock(); // 加锁
                        } 
                        else if(pool->isClosed) break; //线程池关闭了，跳出循环
                        else pool->cond.wait(locker); //没有任务，阻塞，AddTask可唤醒
                    }
                }).detach(); //设置线程分离，无需父线程释放
            }
    }

    ThreadPool() = default; //默认实现无参构造

    ThreadPool(ThreadPool&&) = default;
    
    ~ThreadPool() {
        if(static_cast<bool>(pool_)) { //强转pool_为bool类型,指针不空
            {
                std::lock_guard<std::mutex> locker(pool_->mtx); 
                pool_->isClosed = true; //线程池关闭
            }
            pool_->cond.notify_all(); //唤醒所有
        }
    }
    //把task任务添加到任务队列中
    template<class F>
    void AddTask(F&& task) {
        {
            std::lock_guard<std::mutex> locker(pool_->mtx);
            pool_->tasks.emplace(std::forward<F>(task));
        }
        pool_->cond.notify_one(); //唤醒一个
    }

private:
    struct Pool { //线程池结构体
        std::mutex mtx; //互斥量
        std::condition_variable cond; //条件变量
        bool isClosed;  // 是否关闭线程池
        std::queue<std::function<void()>> tasks; //任务队列
    };
    std::shared_ptr<Pool> pool_; //线程池指针
};


#endif 